<script setup>
import { ref, computed } from 'vue'
import { exportFile, useQuasar } from 'quasar'

const $q = useQuasar()
const props = defineProps({
  isGrid: {
    type: Boolean,
    default: false
  },
  title: {
    type: String,
    default: '表格标题'
  },
  isShowTitle: {
    type: Boolean,
    default: true
  },
  isShowSearch: {
    type: Boolean,
    default: true
  },
  isShowExport: {
    type: Boolean,
    default: false
  },
  exportLabel: {
    type: String,
    default: '导出数据'
  },
  exportDataFileName: {
    type: String,
    default: 'table-export'
  },
  backgroundColor: {
    type: String,
    default: 'rgba(138,209,222,0.58)'
  },
  headerBackgroundColor: {
    type: String,
    default: 'rgba(255,255,255,0.2)'
  },
  headerColor: {
    type: String,
    default: 'white'
  },
  color: {
    type: String,
    default: 'text-black'
  },
  currentPage: {
    type: Number,
    default: 1
  },
  maxPage: {
    type: Number,
    default: 1
  },
  pagination: {
    type: Object,
    default: () => ({
      currentPage: 1,
      maxPage: 100,
      minPage: 1
    })
  },
  rows: {
    type: Array,
    default: () => [
      {
        id: 1,
        name: 'Frozen Yogurt',
        calories: 159,
        fat: 6.0,
        carbs: 24,
        protein: 4.0,
        sodium: 87,
        calcium: '14%',
        iron: '1%'
      },
      {
        id: 2,
        name: 'Frozen Yogurt',
        calories: 159,
        fat: 6.0,
        carbs: 24,
        protein: 4.0,
        sodium: 87,
        calcium: '14%',
        iron: '1%'
      },
      {
        id: 3,
        name: 'Frozen Yogurt',
        calories: 159,
        fat: 6.0,
        carbs: 24,
        protein: 4.0,
        sodium: 87,
        calcium: '14%',
        iron: '1%'
      },
      {
        id: 3,
        name: 'Frozen Yogurt',
        calories: 159,
        fat: 6.0,
        carbs: 24,
        protein: 4.0,
        sodium: 87,
        calcium: '14%',
        iron: '1%'
      },
      {
        id: 3,
        name: 'Frozen Yogurt',
        calories: 159,
        fat: 6.0,
        carbs: 24,
        protein: 4.0,
        sodium: 87,
        calcium: '14%',
        iron: '1%'
      },
      {
        id: 3,
        name: 'Frozen Yogurt',
        calories: 159,
        fat: 6.0,
        carbs: 24,
        protein: 4.0,
        sodium: 87,
        calcium: '14%',
        iron: '1%'
      },
      {
        id: 3,
        name: 'Frozen Yogurt',
        calories: 159,
        fat: 6.0,
        carbs: 24,
        protein: 4.0,
        sodium: 87,
        calcium: '14%',
        iron: '1%'
      }
    ]
  },
  columns: {
    type: Array,
    default: () => [
      {
        name: 'column1',
        required: true,
        label: '列1',
        align: 'left',
        field: (row) => row.name,
        format: (val) => `${val}`,
        sortable: false
      },
      {
        name: 'column2',
        align: 'center',
        label: '列2',
        field: 'calories',
        sortable: false
      },
      { name: 'column3', label: '列3', field: 'fat', sortable: false },
      { name: 'column4', label: '列4', field: 'carbs', sortable: false },
      { name: 'column5', label: '列5', field: 'protein', sortable: false },
      { name: 'column6', label: '列6', field: 'sodium', sortable: false },
      { name: 'column7', label: '列7', field: 'calcium', sortable: false },
      { name: 'column8', label: '列8', field: 'iron', sortable: false }
    ]
  },
  rowKey: {
    type: String,
    default: 'index'
  },
  loading: {
    type: Boolean,
    default: false
  }
})
const emit = defineEmits([
  'onPaginationRequest',
  'onSearchRequest',
  'update:currentPage'
])
const filter = ref('')
// const newPagination = ref({ ...props.pagination })

const page = computed({
  get () {
    return props.currentPage
  },
  set (value) {
    emit('update:currentPage', value)
  }
})

// function updatePagination (props) {
//   emit('onPaginationRequest', props)
// }

function filterMethod (rows, terms, cols) {
  const result = rows.filter((row) => {
    for (const key in row) {
      if (Object.hasOwnProperty.call(row, key)) {
        const value = String(row[key])
        if (value.includes(terms)) {
          return true
        }
      }
    }
    return false
  })
  emit('onSearchRequest', result)
  return result
}

function exportTable () {
  const content = [props.columns.map((col) => wrapCsvValue(col.label))]
    .concat(
      props.rows.map((row) =>
        props.columns
          .map((col) =>
            wrapCsvValue(
              typeof col.field === 'function'
                ? col.field(row)
                : row[col.field === void 0 ? col.name : col.field],
              col.format,
              row
            )
          )
          .join(',')
      )
    )
    .join('\r\n')

  const status = exportFile(
    `${props.exportDataFileName}.csv`,
    content,
    'text/csv'
  )

  if (status !== true) {
    $q.notify({
      message: '浏览器拒绝文件下载...',
      color: 'negative',
      icon: 'warning'
    })
  }
}

function wrapCsvValue (val, formatFn, row) {
  let formatted = formatFn !== void 0 ? formatFn(val, row) : val

  formatted =
    formatted === void 0 || formatted === null ? '' : String(formatted)

  formatted = formatted.split('"').join('""')

  return `"${formatted}"`
}
</script>

<template>
  <div class="table-container" :style="{ height: isGrid ? 'auto' : '100%' }">
    <q-table
      :rows="rows"
      :columns="columns"
      :row-key="rowKey"
      :grid="isGrid"
      :filter="filter"
      dark
      :card-style="{ backgroundColor: backgroundColor }"
      :filter-method="filterMethod"
      rows-per-page-label="每页记录条数"
      :loading="loading"
      binary-state-sort
      :pagination="{rowsPerPage:0}"
      virtual-scroll
      :virtual-scroll-item-size="28"
    >
      <!-- 头部标题插槽自定义 -->
      <template v-slot:top-left>
        <h5
          v-if="isShowTitle"
          style="padding: 0; margin: 0; font-weight: bold"
          :style="{ color: 'white' }"
        >
          {{ title }}
        </h5>
        <slot name="leftTop"></slot>
      </template>
      <!-- 头部搜索插槽自定义 -->
      <template v-slot:top-right>
        <slot name="rightTop">
          <q-btn
            v-if="isShowExport"
            color="primary"
            icon-right="archive"
            class="q-mr-md"
            :label="exportLabel"
            no-caps
            @click="exportTable"
          />
          <q-input
            v-if="isShowSearch"
            class="table-search"
            borderless
            dense
            debounce="300"
            v-model="filter"
            placeholder="请输入查询内容"
          >
            <template v-slot:append>
              <q-icon name="search" />
            </template>
          </q-input>
        </slot>
      </template>
      <!-- 列名插槽自定义样式 -->
      <template v-slot:header="props">
        <q-tr :props="props">
          <q-th
            v-for="col in props.cols"
            :key="col.name"
            :props="props"
            class="column-header"
            :style="{
              backgroundColor: headerBackgroundColor,
              color: headerColor,
            }"
          >
            {{ col.label }}
          </q-th>
        </q-tr>
      </template>

      <!-- 列数据插槽 -->
      <template v-slot:body-cell="props">
        <td class="text-center text-black">
          <slot :name="[props.col.name]" :value="props.row">
            <span>{{ props.value }}</span>
          </slot>
        </td>
      </template>

      <!-- 底部分页插槽 -->
      <!--      <template v-slot:bottom="props">-->
      <template v-slot:bottom>
        <q-pagination
          color="sage-text-white"
          text-color="sage-text-white"
          input-class="sage-text-white"
          v-model="page"
          :max="maxPage"
          :min="1"
          input
          style="margin: auto"
        />
      </template>
    </q-table>
  </div>
</template>

<style scoped lang="scss">
.table-container {
  background-size: cover;
}

.table-container div {
  height: 100%;
}

.column-header {
  font-size: 14px;
  color: black;
  font-weight: bold;
  position: sticky;
  text-align: center;
  z-index: 1;
  top: 0;
  background-color: #ccc;
}

.table-search {
  background-color: rgba(204, 204, 204, 0.86);
  padding: 0 20px;
  border-radius: 42px;
}
</style>
